import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BezierCurveCart(),
    );
  }
}

class BezierCurveCart extends StatefulWidget {
  @override
  _BezierCurveCartState createState() => _BezierCurveCartState();
}

class _BezierCurveCartState extends State<BezierCurveCart> {
  final GlobalKey _key = GlobalKey(debugLabel: 'cartkey');
  Offset _cartOffest;
  @override
  void initState() {
    super.initState();
    // 第一帧之后获取购物车图标位置
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _cartOffest = (_key.currentContext.findRenderObject() as RenderBox)
          .localToGlobal(Offset.zero);
      print(_cartOffest);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('')),
        body: Column(
          children: <Widget>[
            Expanded(
                child: Container(
              padding: EdgeInsets.symmetric(horizontal: 10),
              child: ListView.builder(
                itemBuilder: (context, index) {
                  return Container(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Text('商品  $index'),
                        Builder(
                          builder: (BuildContext context) {
                            return IconButton(
                              icon: Icon(Icons.add_circle_outline, size: 20),
                              onPressed: () {
                                // 因为没有Builder的context表示当前整个控件的context，其上并没有NotificationListener监听，而加上Builder后，context表示Builder控件，其上有NotificationListener监听
                                // 通过 Builder 组件来获取 context
                                RenderBox box = context.findRenderObject();
                                Offset offset = box.localToGlobal(Offset.zero);
                                print(offset);
                                // 点击的时候获取当前 widget 的位置，传入 overlayEntry
                                OverlayEntry _overlayEntry =
                                    OverlayEntry(builder: (context) {
                                  return RedDot(offset, _cartOffest,
                                      Duration(milliseconds: 500));
                                });
                                OverlayEntry _overlayEntry1 =
                                    OverlayEntry(builder: (context) {
                                  return RedDot(offset, _cartOffest,
                                      Duration(milliseconds: 400));
                                });
                                OverlayEntry _overlayEntry2 =
                                    OverlayEntry(builder: (context) {
                                  return RedDot(offset, _cartOffest,
                                      Duration(milliseconds: 300));
                                });
                                // 显示Overlay
                                Overlay.of(context).insert(_overlayEntry);
                                Overlay.of(context).insert(_overlayEntry1);
                                Overlay.of(context).insert(_overlayEntry2);

                                // 清除
                                Future.delayed(Duration(milliseconds: 800), () {
                                  _overlayEntry.remove();
                                  _overlayEntry = null;
                                });
                              },
                            );
                          },
                        )
                      ],
                    ),
                  );
                },
                itemCount: 40,
              ),
            )),
            Divider(
              height: 4,
              color: Colors.grey,
            ),
            Container(
              alignment: Alignment.centerLeft,
              padding: EdgeInsets.all(10),
              child: Icon(Icons.add_shopping_cart, key: _key),
            )
          ],
        ));
  }
}

class RedDot extends StatefulWidget {
  Offset _startPosition;
  Offset _endPosition;
  Duration _duration;
  RedDot(this._startPosition, this._endPosition, this._duration);
  @override
  _RedDotState createState() => _RedDotState();
}

class _RedDotState extends State<RedDot> with SingleTickerProviderStateMixin {
  Animation _animation;
  AnimationController _animationController;
  double _left;
  double _top;

  @override
  void initState() {
    super.initState();
    print('子组件:${widget._startPosition} ${widget._endPosition}');

    _animationController =
        AnimationController(vsync: this, duration: widget._duration);
    _animation = Tween(begin: 0.0, end: 1.0).animate(_animationController);

    double _controllerX = widget._startPosition.dx - 200;
    double _controllerY = widget._startPosition.dy - 100;
    double _endX = widget._endPosition.dx + 6;
    double _endY = widget._endPosition.dy - 3;

    _animation.addListener(() {
      if (mounted) {
        double t = _animation.value;
        setState(() {
          _left = pow(1 - t, 2) * widget._startPosition.dx +
              2 * t * (1 - t) * _controllerX +
              pow(t, 2) * _endX;
          _top = pow(1 - t, 2) * widget._startPosition.dy +
              2 * t * (1 - t) * _controllerY +
              pow(t, 2) * _endY;
        });
      }
    });
    // 显示小圆点的时候动画就开始
    _animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    print(_animation.value);
    return Stack(
      children: <Widget>[
        Positioned(
          left: _left,
          top: _top,
          // 动画的东西
          child: _animation.value != 1
              ? Container(
                  width: 25,
                  height: 25,
                  child: Image.asset('assets/images/ele_turn.png'),
                )
              : SizedBox(),
        )
      ],
    );
  }
}
